home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 019 / clock123.asm < prev    next >
Assembly Source File  |  1985-06-03  |  8KB  |  186 lines

  1. interrupts segment at 0h
  2.           org      1ch*4          ; This is to use INT 1Ch
  3. timer_int label    dword          ; which is the timer interupt
  4. interrupts ends
  5.  
  6. screen    segment at 0b000h       ; A dummy segment to use
  7. screen    ends                    ; as the Extra Segment
  8.  
  9. code_seg  segment
  10.           assume   cs:code_seg
  11.           org      100h           ; org = 100 to make this into
  12.                                   ; a .COM file
  13. first:    jmp      load_clock
  14.  
  15. old_time_int dd    ?              ; The address INT 1Ch normally uses
  16. count500  dw       0              ; Used to update clock every 500 counts
  17. cursor    dw       0              ; Location of the cursor on the screen
  18. video_port         dw   ?         ; Video status port - ckeck for scanning
  19. display   dw       5 dup(133ah)   ; Initial value for the clock
  20.           dw       3 dup(1320h)   ; Add 3 ' 's for AM/PM.
  21.  
  22. clock     proc     near           ; The timer INT will now come here
  23.  
  24.           push     ax             ; Save the registers - good form
  25.           push     cx
  26.           push     di
  27.           push     si
  28.           push     es
  29.  
  30.           pushf                   ; First call old time interrupt
  31.           call     old_time_int
  32.  
  33.           mov      cx,count500    ; Prepare to test if we
  34.           inc      cx             ; should recalculate the time - done
  35.           cmp      cx,500         ; every 500 timer counts
  36.           jb       dont_recalculate
  37.           call     calc           ; Recalculate the time
  38.           mov      cx,0           ; Reset Count500
  39. dont_recalculate:
  40.           mov      count500,cx    ; Store incremented or cleared value
  41.  
  42.           assume   es:screen      ; Set up screen as the Extra Segment
  43.           mov      cx,screen
  44.           mov      es,cx
  45.           mov      dx,video_port  ; This is the screen status port
  46.           mov      di,cursor      ; Set up cursor on screen as destination
  47.           lea      si,display     ; Set up the display in memory as source
  48.           mov      cx,8           ; To move char only
  49.  
  50.           cli
  51.  
  52. scan_low:                         ; Start waiting for a new horizontal scan
  53.           in       al,dx          ; i.e. the the vidio controller scan
  54.           test     al,1           ; status is low.
  55.           jnz      scan_low
  56.  
  57.           mov      ah,cs:[si]     ; Move byte to be written into AH
  58.  
  59. scan_high:                        ; After port has gone low, it must go high
  60.           in       al,dx          ; before it is safe to write directly
  61.           test     al,1           ; to the screen buffer in memory
  62.           jz       scan_high
  63.  
  64.           mov      es:[di],ah     ; Move to screen one byte at a time.
  65.           inc      di             ; Position to attribute byte
  66.           inc      si             ; on screen.
  67.           inc      di             ; Increment again to position
  68.           inc      si             ; past the attribute byte
  69.  
  70.           loop     scan_low       ; Go back foe next byte
  71.           sti
  72.  
  73.           pop      es             ; Here are required pops to exit
  74.           pop      si
  75.           pop      di
  76.           pop      cx
  77.           pop      ax
  78.  
  79.           iret                    ; Aninterrupt needs an IRET
  80.  
  81. clock     endp
  82.  
  83. calc      proc near               ; Here we recalculate the time and store it
  84.           push     ax             ; Puushes to save everytheing that
  85.           push     bx             ; gets destroyed
  86.           push     cx
  87.           push     dx
  88.  
  89.           xor      ax,ax          ; Set up for clock read.
  90.           int      1ah            ; Read the clock.
  91.           push     dx             ; Save low(minutes) portion.
  92.           mov      ax,cx          ; Move high(hours) portion to AX.
  93.  
  94.  
  95.  
  96. check:    cmp      ax,24          ; Make sure it's less than 24
  97.           jle      valid_time
  98.           sub      ax,24          ; If not, keep subtracting until it is.
  99.           jmp      check
  100. valid_time:
  101.           lea      bx,display     ; Set up BX as pointer to display in memory
  102.           mov      byte ptr cs:[bx+14],'M' ; Move the 'M' into the display.
  103.  
  104.           cmp      ax,0           ; Is it between 12 & 1 AM?
  105.           jne      after_1am      ; No, check other times.
  106.           mov      ax,012         ; Yes, make it '12',
  107.           jmp      am             ;  and set to display 'AM'
  108. after_1am:
  109.           cmp      ax,12          ; Is it between 1 & 12 AM?
  110.           jl       am             ; Yes, set to display 'AM'
  111.           cmp      ax,12          ; Is it between 12 & 1 PM?
  112.           je       pm             ; Yes, set to display 'PM'
  113.           sub      ax,12          ; If not, take off another 12.
  114.           cmp      ax,12          ; Is it after midnight?
  115.           je       am             ; Yes, set to display 'AM'
  116. pm:       mov      byte ptr cs:[bx+12],'P' ; Otherwise move 'P' into the display.
  117.           jmp      am_pm_done     ; Continue.
  118. am:       mov      byte ptr cs:[bx+12],'A' ; Move an 'A' into the display.
  119. am_pm_done:
  120.           aam                     ; Convert AX to BCD - a nice command
  121.           add      ax,3030h       ; Add '0' to both bytes in AX to make ASCII
  122.           cmp      ah,'0'         ; Is the 1st diget '0'?
  123.           jne      dont_edit      ; Then don't blank the character.
  124.           mov      ah,' '         ; Otherwise, put a space in AH.
  125. dont_edit:
  126.           mov      cs:[bx],ah     ; Move first hours digit into display
  127.           mov      cs:[bx+2],al   ; Then the second digit
  128.  
  129.           pop      ax             ; Get low portion of clock from stack.
  130.           mov      cx,8           ; We want to multiply minutes by 60 and
  131.           shr      ax,cl          ; divide by 65536, so multiply by 60 and shift
  132.           mov      dx,60          ; right 16 bits. 60 secs = 65536 ticks.
  133.           mul      dl
  134.           shr      ax,cl
  135.           aam                     ; Again convert AX to Binary Coded Decimal
  136.           add      ax,3030h       ; Add to make two ASCII characters
  137.           mov      cs:[bx+6],ah   ; and move them into the display in memory
  138.           mov      cs:[bx+8],al
  139.  
  140.                                   ; Restore registers
  141.           pop      dx
  142.           pop      cx
  143.           pop      bx
  144.           pop      ax
  145.  
  146.           ret
  147. calc      endp
  148.  
  149. load_clock proc near              ; This procedure initializes everything
  150.           assume   ds:interrupts  ; The Data Segment will be the interrupt area
  151.           mov      ax,interrupts
  152.           mov      ds,ax
  153.           cli
  154.  
  155.           mov      ax,timer_int       ; Get the old interrupt service routine
  156.           mov      old_time_int,ax    ; address and put it into our location
  157.           mov      ax,timer_int[2]    ; OLD_TIME_INT so we can still call it
  158.           mov      old_time_int[2],ax
  159.  
  160.           mov      timer_int,offset clock ; Now load the address of our clock
  161.           mov      timer_int[2],cs    ; routine into TIMER_INT so the timer
  162.                                       ; interrupt will call CLOCK
  163.           sti
  164.  
  165.           mov      ah,15              ; Ask for service 15 of INT 10H
  166.           int      10h                ; This tells us how the display is set up
  167.           sub      ah,20              ; Move to twenty places before edge
  168.           shl      ah,1               ; Mult by two (char and attribute bytes)
  169.           mov      byte ptr cursor,ah ; Move cursor to it's memory location
  170.           mov      video_port,03bah   ; Assume this is a monochrome display
  171.           test     al,4               ; Is it?
  172.           jnz      get_time           ; Yes - jump out
  173.           add      cursor,8000h       ; No - set up for graphics display
  174.           mov      video_port,03dah
  175.  
  176. get_time:
  177.           call     calc  ; This is to avoid showing 00:00 for first 500 counts
  178.           mov      dx,offset load_clock ; Set up for everything but LOAD_CLOCK
  179.           int      27h                ; to stay attached to DOS
  180.  
  181. load_clock         endp
  182.  
  183.           code_seg ends
  184.  
  185.           end      first ; END FIRST so 8088 will go to FIRST first
  186.